/*
* Copyright (C) Microsoft. All rights reserved.  
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not 
* use this file except in compliance with the License.  You may obtain a copy 
* of the License at http://www.apache.org/licenses/LICENSE-2.0  
* 
* THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
* WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
* MERCHANTABLITY OR NON-INFRINGEMENT. 
*
* See the Apache License, Version 2.0 for specific language governing 
* permissions and limitations under the License.
*
*/
#pragma once

#include <baja/common.hpp>
#include <journal/models/types.h>
#include <journal/models/db/table_interfaces.h>


namespace journal { namespace model {

namespace b = baja;
namespace s = baja::storage;

struct iinternal_notebook_model : public b::ibase
{
    BAJA_INTERFACE_NOTAG(iinternal_notebook_model);

    // starts the loading thread in the background. a call to startLoadingAsync() has to be made
    // before calling loadPageAsync() or else loadPageAsync() will block until startLoadingAsync()
    // is called.
    virtual void startLoadingAsync() = 0;

    // discards all the loadPageAsync() request that have been placed in the queue.
    virtual void cancelLoadingAsync() = 0;

    // places a request in the load queue to load a page.
    // on completion: inotebook_model_observer::onPageLoadLevelSet() is called.
    virtual void loadPageAsync(
        const b::uint32& pageId,
        const page_level& targetLevel) = 0;
};

struct iinternal_page_model_observer : public baja::ibase
{
    BAJA_INTERFACE_NOTAG(iinternal_page_model_observer);

    // fired at the completion of a the initialize() operation.
    // The initialize() operation is necessary for any page that is not loaded from disk.
    virtual void onPageInitialized(
        const std::shared_ptr<ipage_model>& page) = 0;
};

struct iinternal_page_model : public b::ibase
{
    BAJA_INTERFACE_NOTAG(iinternal_page_model);

    virtual baja::int32 addInternalObserver(const std::shared_ptr<iinternal_page_model_observer>& observer) = 0;
    virtual void removeInternalObserver(const b::int32 cookie)= 0;

    // call this method on a newly created page.
    // do not call this method on a page loaded from disk. instead, call setLoadLevelAsync().
    virtual void initialize(const b::uint32& pagePaperType) = 0;

    // load page synchronously
    virtual void load(
        const b::uint32 pass,
        const page_level targetLevel) = 0;

    // stop the current load operation
    virtual void stopLoading() = 0;

    // unload page synchronously
    virtual void unload() = 0;

    // saves all content except thumbnail.
    virtual void createInDB() = 0;

    virtual void dispose() = 0;
};


struct iinternal_ink_surface_model : public b::ibase
{
    BAJA_INTERFACE_NOTAG(iinternal_ink_surface_model);

    virtual b::uint32 sizeInMemory() = 0;

    virtual void initialize() = 0;
    virtual void load(baja::uint32 pass, bool& done) = 0;
    virtual void unload() = 0;
    virtual void createInDB() = 0;
    virtual void dispose() = 0;
};

struct iinternal_ink_stroke_model : public b::ibase
{
    BAJA_INTERFACE_NOTAG(iinternal_ink_stroke_model);

    virtual b::uint32 sizeInMemory() = 0;
};

struct iinternal_model_blob : public b::ibase
{
    BAJA_INTERFACE_NOTAG(iinternal_model_blob);

    virtual b::uint32 blobSize() = 0;
    virtual void packToBlob(s::binary_blob& outBlob, b::uint32& offset) = 0;
    virtual void unpackFromBlob(const s::binary_blob& inBlob, b::uint32& offset) = 0;
};

struct iinternal_photo_model : public b::ibase
{
    BAJA_INTERFACE_NOTAG(iinternal_photo_model);

    virtual void initializeAsync(
        const std::shared_ptr<baja::storage::istorage_file>& originalStorageFile,
        const b::float32& scale,
        const m::point2d& position,
        const b::float32& angle,
        const std::function<void()>& setCompleted
        ) = 0;

    virtual void loadAsync(std::function<void()> loadCompleted) = 0;
    virtual void unload() = 0;
    virtual void createInDB() = 0;
    virtual void activate(
        const b::Boolean& active) = 0;
    virtual void dispose() = 0;
};

struct ipage_model_factory : public b::ibase
{
    BAJA_INTERFACE_NOTAG(ipage_model_factory);

    virtual void 
        getPersistedPageIds(
            std::vector<b::uint32>& ids
            ) = 0;

    virtual std::shared_ptr<ipage_model>
        createPage(
            const std::shared_ptr<inotebook_model>& parent
            ) = 0;

    virtual std::shared_ptr<ipage_model>
        recreatePage(
            const std::shared_ptr<inotebook_model>& parent, 
            const b::uint32 pageId
            ) = 0;

    virtual b::uint32
        typeToken() = 0;
};

struct iink_surface_model_factory : public b::ibase
{
    BAJA_INTERFACE_NOTAG(iink_surface_model_factory);

    virtual void 
        getPersistedInkSurfaceIds(
            b::uint32 pageId,
            std::vector<b::uint32>& ids
            ) = 0;

    virtual void
        removeFromDB(
            const b::uint32& pageId
            ) = 0;

    virtual std::shared_ptr<iink_surface_model>
        createInkSurface(
            const std::shared_ptr<ipage_model>& parent
            ) = 0;

    virtual std::shared_ptr<iink_surface_model>
        recreateInkSurface(
            const std::shared_ptr<ipage_model>& parent,
            const b::uint32 inkSurfaceId
            ) = 0;
};

struct iink_stroke_model_factory : public b::ibase
{
    BAJA_INTERFACE_NOTAG(iink_stroke_model_factory);

    virtual std::shared_ptr<iink_stroke_model>
        createInkStroke(
            const std::shared_ptr<iink_surface_model>& parent
            ) = 0;

    virtual std::shared_ptr<iink_stroke_model>
        recreateInkStroke(
            const std::shared_ptr<iink_surface_model>& parent,
            const b::uint32& inkStrokeId
            ) = 0;

    virtual std::shared_ptr<iink_stroke_model>
        recreateInkStroke(
            const std::shared_ptr<iink_surface_model>& parent,
            const s::binary_blob& inBlob, b::uint32& offset
            ) = 0;

};

struct iphoto_model_factory : public b::ibase
{
    BAJA_INTERFACE_NOTAG(iphoto_model_factory);

    virtual void
        getPersistedPhotoIds(
            b::uint32 pageId,
            std::vector<b::uint32>& ids
            ) = 0;

    virtual void
        removeFromDB(
            const b::uint32& pageId
            ) = 0;

    virtual std::shared_ptr<iphoto_model>
        createPhoto(
            const std::shared_ptr<ipage_model>& parent
            ) = 0;

    virtual std::shared_ptr<iphoto_model>
        recreatePhoto(
            const std::shared_ptr<ipage_model>& parent,
            const b::uint32& photoId
            ) = 0;

    virtual b::uint32
        typeToken() = 0;
};

}} // namespace journal::models